/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wwcontrolserver.controls;

import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 *
 * @author Michael Ferry
 */
public class DutyCycleControlState extends AbstractControlState implements Serializable {
    public static enum OperationMode {CONTINUOUS, SCHEDULED, OFF};
    public static final boolean DefaultCentralTimerNotficationState = false;
    //Parameters which can be set by the user
    protected OperationMode OpMode;
    //These parameters are only useful for Scheduled run times
    protected Double DutyCyclePeriod = null;
    protected Double OnTimePeriod = null;
    protected TimeUnit Tunit = null;
    //Should be in MilliSeconds
    protected Long ScheduledControlStartTimeMilli = null;
    protected Long DutyCyclePeriodMilli = null;
    protected Long OnTimePeriodMilli = null;
    private static final long serialVersionUID = -5800329435692472136L;
    
    //Default control state is OFF
    public DutyCycleControlState(int ControlID, String ControlName) {
        super(ControlID, ControlName, DefaultCentralTimerNotficationState);
        this.OpMode = OperationMode.OFF;
    }

    public DutyCycleControlState(int ControlID, String ControlName, OperationMode OpMode) {
        super(ControlID, ControlName, DefaultCentralTimerNotficationState);
        this.OpMode = OpMode;
    }

    public DutyCycleControlState(int ControlID,
            Long StartTimeMilli, Double OnTimePeriod, Double DutyCyclePeriod, TimeUnit Tunit) {
        super(ControlID, null, DefaultCentralTimerNotficationState);

        this.OpMode = OperationMode.SCHEDULED;
        this.ScheduledControlStartTimeMilli = StartTimeMilli;
        this.OnTimePeriod = OnTimePeriod;
        this.DutyCyclePeriod = DutyCyclePeriod;
        this.Tunit = Tunit;
        this.DutyCyclePeriodMilli = (long) (DutyCyclePeriod * Tunit.toMillis(1));
        this.OnTimePeriodMilli = (long) (OnTimePeriod * Tunit.toMillis(1));
    }
    
    public DutyCycleControlState(int ControlID, Double OnTimePeriod, Double DutyCyclePeriod, TimeUnit Tunit) {
        super(ControlID, null, DefaultCentralTimerNotficationState);
        
        //Use this start
        this.OpMode = OperationMode.SCHEDULED;
        this.OnTimePeriod = OnTimePeriod;
        this.DutyCyclePeriod = DutyCyclePeriod;
        this.Tunit = Tunit;
        //For some reason the unit conversion only accepts long arguments.  This doesn't
        //work for example if you want to convert double times.  The below code essentially
        //converts a time to a long millisecond.  Note the input time should probably be in seconds
        //minutes or hours
        this.DutyCyclePeriodMilli = (long) (DutyCyclePeriod * Tunit.toMillis(1));
        this.OnTimePeriodMilli = (long) (OnTimePeriod * Tunit.toMillis(1));
        //int x=1;
    }
    protected void SetScheduledControlStartTime(long StartTimeMilli){
        ScheduledControlStartTimeMilli = StartTimeMilli;
    }
    protected void SetScheduledControlStartTime(){
        ScheduledControlStartTimeMilli = System.currentTimeMillis();
    }
    @Override
    protected void UpdateControlState(AbstractControlState AbstractState) throws Exception {
        //Determine if this is the correct state
        if (AbstractState instanceof DutyCycleControlState) {
            
            DutyCycleControlState DesiredDutyCycleState = (DutyCycleControlState) AbstractState;

            this.OpMode = DesiredDutyCycleState.OpMode;
            switch (this.OpMode) {
                case CONTINUOUS:

                    this.DutyCyclePeriod = null;
                    this.OnTimePeriod = null;
                    this.Tunit = null;
                    //Should be in MilliSeconds
                    this.ScheduledControlStartTimeMilli = null;
                    this.DutyCyclePeriodMilli = null;
                    this.OnTimePeriodMilli = null;

                    // SetContinuousOperation();
                    break;
                case SCHEDULED:
                    this.DutyCyclePeriod = DesiredDutyCycleState.DutyCyclePeriod;
                    this.OnTimePeriod = DesiredDutyCycleState.OnTimePeriod;
                    this.Tunit = DesiredDutyCycleState.Tunit;
                    //Should be in MilliSeconds
                    this.ScheduledControlStartTimeMilli = DesiredDutyCycleState.ScheduledControlStartTimeMilli;
                    this.DutyCyclePeriodMilli = DesiredDutyCycleState.DutyCyclePeriodMilli;
                    this.OnTimePeriodMilli = DesiredDutyCycleState.OnTimePeriodMilli;

                    break;
                case OFF:
                    this.DutyCyclePeriod = null;
                    this.OnTimePeriod = null;
                    this.Tunit = null;
                    //Should be in MilliSeconds
                    this.ScheduledControlStartTimeMilli = null;
                    this.DutyCyclePeriodMilli = null;
                    this.OnTimePeriodMilli = null;

                    break;
            }
        } else {
            throw new Exception();
        }
    }
    public OperationMode GetOperationMode(){
        return this.OpMode;
    }
    @Override
    public void SetOffState(){
        this.OpMode = DutyCycleControlState.OperationMode.OFF;
    }
}
